#include "particles.h"
#include <d3d9.h>

#define rnd_float(x) ((float)(rand()%x)/(float)x)

emitter::emitter(u32 _sz, vector3 _pos,texture* _tex)
{
	m_texture = _tex;
	m_pos = _pos;
	m_size = _sz;
	m_particles = new particle[_sz];
}

emitter::~emitter()
{
	if(m_particles)
		delete m_particles;
}

void emitter::reset()
{
	for(u32 i=0;i<m_size;i++)
		set_def(i);
}

smoke::smoke(u32 _sz,vector3 _pos,float _height,texture* _tex):emitter(_sz,_pos,_tex)
{
	m_height = _height;
	reset();
}

void smoke::set_def(u32 _i)
{
	m_particles[_i].pos = m_pos;
	m_particles[_i].vel = vector3(rnd_float(1000)*0.0005f-0.00025f, 0.01f+rnd_float(1000)*0.002f,rnd_float(1000)*0.0005f-0.00025f);
	m_particles[_i].size = 0.1f;
}
void smoke::update(u32 _dt)
{
	for(u32 i=0;i<m_size;i++)
	{
		m_particles[i].pos += m_particles[i].vel * (float)_dt;
		m_particles[i].size = fabs(2.5f/m_height*(m_particles[i].pos.y-m_pos.y)+0.5f);
		if(m_particles[i].pos.y>m_pos.y+m_height) 
			set_def(i);
	}
}

void smoke::draw()
{
	/*
	IDirect3DDevice9* dev = render::get_inst().get_device();

	D3DCHECK(dev->SetRenderState(D3DRS_ALPHABLENDENABLE, true));
	//D3DCHECK(dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR));
	//D3DCHECK(dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO));
	D3DCHECK(dev->SetRenderState(D3DRS_LIGHTING, false));
	D3DCHECK(dev->SetRenderState(D3DRS_ZWRITEENABLE, false));

	matrix4 m,oldview;
	m.identity();

	D3DCHECK(dev->GetTransform(D3DTS_VIEW,(D3DMATRIX*)oldview.mat));

	render::get_inst().set_view(m);
	render::get_inst().set_world(m);

	render::get_inst().set_cullmode(cullmode_none);

	render::get_inst().set_texture(0,m_texture);

	vector3 pos;
	float alpha;
	color c;

	for(u32 i=0;i<m_size;i++)
	{
		pos = oldview * m_particles[i].pos;
		alpha = 1.0f-1.0f/m_height*(m_particles[i].pos.y-m_pos.y);
		c = color(1.0f,1.0f,1.0f,alpha);

		m_vrt[2] = ptc_vertex(pos+vector3(1.0f*m_particles[i].size,-1.0f*m_particles[i].size,0.0f),c.argb(),vector2(1.0f,1.0f));
		m_vrt[0] = ptc_vertex(pos+vector3(-1.0f*m_particles[i].size,-1.0f*m_particles[i].size,0.0f),c.argb(),vector2(0.0f,1.0f));
		m_vrt[3] = ptc_vertex(pos+vector3(1.0f*m_particles[i].size,1.0f*m_particles[i].size,0.0f),c.argb(),vector2(1.0f,0.0f));
		m_vrt[1] = ptc_vertex(pos+vector3(-1.0f*m_particles[i].size,1.0f*m_particles[i].size,0.0f),c.argb(),vector2(0.0f,0.0f));

		D3DCHECK(dev->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1));
		D3DCHECK(dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,m_vrt,sizeof(ptc_vertex)));
	}

	render::get_inst().set_texture(0,0);
	render::get_inst().set_view(oldview);

	D3DCHECK(dev->SetRenderState(D3DRS_ALPHABLENDENABLE, false));
	D3DCHECK(dev->SetRenderState(D3DRS_LIGHTING, true));
	D3DCHECK(dev->SetRenderState(D3DRS_ZWRITEENABLE, true));*/
}

exploser::exploser(u32 _sz,float _radius,texture* _tex):emitter(_sz,vector3(),_tex)
{
	m_radius = _radius;
	m_cntr = _sz;
	reset();
}

void exploser::set_def(u32 _i)
{
	m_particles[_i].alive = false;
	m_particles[_i].age = 0;
}

void exploser::exploid(vector3 _pos, u32 _sz, float _diam)
{
	u32 i,maxlivtime,max_id;

	maxlivtime = 0;
	max_id = 0;

	for(i=0;i<m_size;i++)
	{
		if(!m_particles[i].alive)
		{
			m_particles[i].alive = true;
			m_particles[i].age = 0;
			m_particles[i].oldpos = _pos;
			m_particles[i].pos = _pos;
			m_particles[i].vel = vector3(rnd_float(1000)*0.06f-0.03f,rnd_float(1000)*0.06f-0.03f,rnd_float(1000)*0.06f-0.03f);
			m_particles[i].size = _diam;
			_sz--;
			if(_sz<=0)
				break;
		}
	}
	if(_sz>0)
	{
		while(_sz>0)
		{
			maxlivtime = 0;
			max_id = 0;
			for(i=0;i<m_size;i++)
			{
				if(m_particles[i].age > maxlivtime)
				{
					maxlivtime = m_particles[i].age;
					max_id = i;
				}
			}
			m_particles[i].alive = true;
			m_particles[max_id].age = 0;
			m_particles[max_id].oldpos = _pos;
			m_particles[max_id].pos = _pos;
			m_particles[max_id].vel = vector3(rnd_float(1000)*0.06f-0.03f,rnd_float(1000)*0.06f-0.03f,rnd_float(1000)*0.06f-0.03f);
			m_particles[i].size = _diam;
			_sz--;
		}
	}
}

void exploser::update(u32 _dt)
{
	for(u32 i=0;i<m_size;i++)
	{
		if(!m_particles[i].alive)
			continue;

		m_particles[i].age += _dt;
		m_particles[i].pos += m_particles[i].vel * (float)_dt;

		if(fabs(m_particles[i].pos.x - m_particles[i].oldpos.x)>m_radius||
		   fabs(m_particles[i].pos.y - m_particles[i].oldpos.y)>m_radius||
		   fabs(m_particles[i].pos.z - m_particles[i].oldpos.z)>m_radius) 
		{
			m_particles[i].alive = false;
		}
	}
}

void exploser::draw()
{
	/*
	IDirect3DDevice9* dev = render::get_inst().get_device();

	D3DCHECK(dev->SetRenderState(D3DRS_ALPHABLENDENABLE, true));
	//D3DCHECK(dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA));
	//D3DCHECK(dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO));
	D3DCHECK(dev->SetRenderState(D3DRS_LIGHTING, false));
	D3DCHECK(dev->SetRenderState(D3DRS_ZWRITEENABLE, false));

	matrix4 m,oldview;
	m.identity();

	D3DCHECK(dev->GetTransform(D3DTS_VIEW,(D3DMATRIX*)oldview.mat));

	render::get_inst().set_view(m);
	render::get_inst().set_world(m);

	render::get_inst().set_cullmode(cullmode_none);

	render::get_inst().set_texture(0,m_texture);

	vector3 pos;
	float alpha;
	color c;

	for(u32 i=0;i<m_size;i++)
	{
		if(!m_particles[i].alive)
			continue;

		pos = oldview * m_particles[i].pos;
		alpha = 1.0f-1.0f/m_radius*fabs(m_particles[i].pos.x-m_particles[i].oldpos.x);
		c = color(1.0f,1.0f,1.0f,alpha);

		m_vrt[2] = ptc_vertex(pos+vector3(1.0f*m_particles[i].size,-1.0f*m_particles[i].size,0.0f),c.argb(),vector2(1.0f,1.0f));
		m_vrt[0] = ptc_vertex(pos+vector3(-1.0f*m_particles[i].size,-1.0f*m_particles[i].size,0.0f),c.argb(),vector2(0.0f,1.0f));
		m_vrt[3] = ptc_vertex(pos+vector3(1.0f*m_particles[i].size,1.0f*m_particles[i].size,0.0f),c.argb(),vector2(1.0f,0.0f));
		m_vrt[1] = ptc_vertex(pos+vector3(-1.0f*m_particles[i].size,1.0f*m_particles[i].size,0.0f),c.argb(),vector2(0.0f,0.0f));

		D3DCHECK(dev->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1));
		D3DCHECK(dev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,m_vrt,sizeof(ptc_vertex)));
	}

	render::get_inst().set_texture(0,0);
	render::get_inst().set_view(oldview);

	D3DCHECK(dev->SetRenderState(D3DRS_ALPHABLENDENABLE, false));
	D3DCHECK(dev->SetRenderState(D3DRS_LIGHTING, true));
	D3DCHECK(dev->SetRenderState(D3DRS_ZWRITEENABLE, true));\
	*/
}
